﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.IO.Ports;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Windows.Forms;
using WeifenLuo.WinFormsUI.Docking;
using System.Xml;
using ControlExs;

namespace nsGumController
{
    public partial class CGumController : Form
    {
        public CGumController()
        {
            InitializeComponent();
        }

        static public DockMessageBox mDockMessageBox = new DockMessageBox();
        static public CLog mLog = new CLog(mDockMessageBox.rtxtShowMessage);  // 此语句的上下顺序不能变，存在依赖关系
        static public DockSerialProtocol mDockSerialProtocol = new DockSerialProtocol();
        static public DockCommandBtn mDockCommandBtn = new DockCommandBtn();
        static public DockSetParameter mDockSetParameter = new DockSetParameter();
        static public MASHINE_INFO mMashineInfo = new MASHINE_INFO();
        static public DockMain mDockMain = new DockMain();

        private bool isAutoUpdate = false;      // 启动后是否检查升级
        private bool isSaveTips = false;        // 关闭后是否提示保存
        private UpdateGumControllerService.WebService1 wsUpdate = new UpdateGumControllerService.WebService1();

        private void CGumController_Load(object sender, EventArgs e)
        {
            dockPanel1.DockRightPortion = 0.285;
            dockPanel1.DockBottomPortion = 0.3;
            mDockMain.Show(dockPanel1, DockState.Document);
            mDockCommandBtn.Show(dockPanel1, DockState.DockRight);
            mDockSerialProtocol.Show(dockPanel1, DockState.DockRight);
            mDockMessageBox.Show(dockPanel1, DockState.DockBottom);

            mDockSerialProtocol.Activate();
            LoadConfigFile();

            DoUpdate();
        }

        /// <summary>
        /// 更新任务主函数
        /// </summary>
        private void DoUpdate()
        {
            if (!isAutoUpdate)
            {
                return;
            }

            Thread updateThread = new Thread(UpdataThread);
            updateThread.Start();
        }

        void UpdataThread()
        {
            mLog.LogMessage("检查更新...\n");
            string strVer = "";
            try
            {
                strVer = wsUpdate.GetVer();
            }
            catch (System.Exception ex)
            {
                mLog.LogMessage(ex.Message);
                return;
            }
            if (Application.ProductVersion.CompareTo(strVer) < 0)
            {
                string message = "有可用更新，是否下载?";
                string caption = "更新";
                var result = QQMessageBox.Show(null, message, caption,
                                           QQMessageBoxIcon.Question,
                                           QQMessageBoxButtons.OKCancel);

                if (result != DialogResult.OK)
                {
                    return;
                }

                mLog.LogMessage("开始下载...\n");
                XmlDocument doc = wsUpdate.GetUpdateData();
                doc.Save(Application.StartupPath + @"/update.xml");

                message = "下载完毕，是否启动更新?";
                caption = "更新";
                result = QQMessageBox.Show(null, message, caption,
                                           QQMessageBoxIcon.Question,
                                           QQMessageBoxButtons.OKCancel);

                if (result != DialogResult.OK)
                {
                    return;
                }
                SaveConfigFile();   // 用于写入当前程序的名称
                try
                {
                	System.Diagnostics.Process.Start(Application.StartupPath + @"/update.exe");
                }
                catch (System.Exception ex)
                {
                    mLog.LogMessage("%s\n", ex.Message);
                    mLog.LogMessage("启动更新程序失败\n");
                    return;
                }
                Application.Exit();
            }
        }

        protected override void OnClosing(CancelEventArgs e)
        {
            mDockMain.Close();
            mDockCommandBtn.Close();
            mDockMessageBox.Close();
            mDockSerialProtocol.Close();
            mDockSetParameter.Close();
        }

        #region byte数组与结构体转换函数
        /// <summary>
        /// 结构体转byte数组
        /// </summary>
        /// <param name="structObj">要转换的结构体</param>
        /// <returns>转换后的byte数组</returns>
        public static byte[] StructToBytes(object structObj)
        {
            //得到结构体的大小
            int size = Marshal.SizeOf(structObj);
            //创建byte数组
            byte[] bytes = new byte[size];
            //分配结构体大小的内存空间
            IntPtr structPtr = Marshal.AllocHGlobal(size);
            //将结构体拷到分配好的内存空间
            Marshal.StructureToPtr(structObj, structPtr, false);
            //从内存空间拷到byte数组
            Marshal.Copy(structPtr, bytes, 0, size);
            //释放内存空间
            Marshal.FreeHGlobal(structPtr);
            //返回byte数组
            return bytes;
        }

        /// <summary>
        /// byte数组转结构体
        /// </summary>
        /// <param name="bytes">byte数组</param>
        /// <param name="type">结构体类型</param>
        /// <returns>转换后的结构体</returns>
        public static object BytesToStuct(byte[] bytes, Type type)
        {
            //得到结构体的大小
            int size = Marshal.SizeOf(type);
            //byte数组长度小于结构体的大小
            if (size > bytes.Length)
            {
                //返回空
                return null;
            }
            //分配结构体大小的内存空间
            IntPtr structPtr = Marshal.AllocHGlobal(size);
            //将byte数组拷到分配好的内存空间
            Marshal.Copy(bytes, 0, structPtr, size);
            //将内存空间转换为目标结构体
            object obj = Marshal.PtrToStructure(structPtr, type);
            //释放内存空间
            Marshal.FreeHGlobal(structPtr);
            //返回结构体
            return obj;
        }
        #endregion

        private void LoadConfigFile()
        {
            CIni ini = new CIni(Directory.GetCurrentDirectory() + "\\Config.cfg");
            if (ini.ReadBoolValue("Config", "NeedToLog") == true)
            {
                记录Log文件ToolStripMenuItem.Checked = true;
            }
            else
            {
                记录Log文件ToolStripMenuItem.Checked = false;
            }
            mLog.IsLogToFile = 记录Log文件ToolStripMenuItem.Checked;

            if (ini.ReadBoolValue("Config", "SaveTips") == true)
            {
                退出后提示保存ToolStripMenuItem.Checked = true;
            }
            else
            {
                退出后提示保存ToolStripMenuItem.Checked = false;
            }
            isSaveTips = 退出后提示保存ToolStripMenuItem.Checked;

            if (ini.ReadBoolValue("Config", "AutoUpdate") == true)
            {
                启动时检查更新ToolStripMenuItem.Checked = true;
            }
            else
            {
                启动时检查更新ToolStripMenuItem.Checked = false;
            }
            isAutoUpdate = 启动时检查更新ToolStripMenuItem.Checked;
        }

        private void SaveConfigFile()
        {
            CIni ini = new CIni(Directory.GetCurrentDirectory() + "\\Config.cfg");
            ini.Write("Config", "NeedToLog", 记录Log文件ToolStripMenuItem.Checked.ToString());
            ini.Write("Config", "SaveTips", 退出后提示保存ToolStripMenuItem.Checked.ToString());
            ini.Write("Config", "AutoUpdate", 启动时检查更新ToolStripMenuItem.Checked.ToString());
            ini.Write("Config", "AppName", System.Diagnostics.Process.GetCurrentProcess().ProcessName.ToLower());
        }

        private void ExportIniFile(string iniPath)
        {
            CIni ini = new CIni(iniPath);

            //////////////////////////////////////////////////////////////////////////
            // 参数设置
            //////////////////////////////////////////////////////////////////////////
            int iTemp = mDockSetParameter.originXSet;
            ini.Write("Parameter", "OriginX", iTemp.ToString());
            iTemp = mDockSetParameter.originYSet;
            ini.Write("Parameter", "OriginY", iTemp.ToString());
            uint uiTemp = mDockSetParameter.pwmCycleTDefault;
            ini.Write("Parameter", "PwmCycleTDefault", uiTemp.ToString());
            uiTemp = mDockSetParameter.pwmCycleTReset;
            ini.Write("Parameter", "PwmCycleTReset", uiTemp.ToString());
            uiTemp = mDockSetParameter.pwmCycleTGum;
            ini.Write("Parameter", "PwmCycleTGum", uiTemp.ToString());
            uiTemp = mDockSetParameter.pwmCycleTChabu;
            ini.Write("Parameter", "PwmCycleTChabu", uiTemp.ToString());
            uiTemp = mDockSetParameter.pwmChabuDelay;
            ini.Write("Parameter", "PwmChabuDelay", uiTemp.ToString());

            //////////////////////////////////////////////////////////////////////////
            // 自动控制指令
            //////////////////////////////////////////////////////////////////////////
            int actionNums = mDockSetParameter.mAutoActionList.Count;
            ini.Write("ActionInfo", "Nums", actionNums.ToString());     // 写入总共有多少个步骤
            for (int i = 0; i < actionNums; i++)
            {
                string strSection = string.Format("Action{0}", i);
                ini.Write(strSection, "Cmd", mDockSetParameter.mAutoActionList[i].Cmd.GetHashCode().ToString());
                ini.Write(strSection, "StartX", mDockSetParameter.mAutoActionList[i].Point1X.ToString());
                ini.Write(strSection, "StartY", mDockSetParameter.mAutoActionList[i].Point1Y.ToString());
                ini.Write(strSection, "EndX", mDockSetParameter.mAutoActionList[i].Point2X.ToString());
                ini.Write(strSection, "EndY", mDockSetParameter.mAutoActionList[i].Point2Y.ToString());
                ini.Write(strSection, "Radius", mDockSetParameter.mAutoActionList[i].Radius.ToString());
                ini.Write(strSection, "Mode", mDockSetParameter.mAutoActionList[i].Mode.ToString());
            }
        }

        private void ImportIniFile(string iniPath)
        {
            CIni ini = new CIni(iniPath);

            //////////////////////////////////////////////////////////////////////////
            // 参数设置
            //////////////////////////////////////////////////////////////////////////
            mDockSetParameter.originXSet = ini.ReadIntValue("Parameter", "OriginX");
            mDockSetParameter.originYSet = ini.ReadIntValue("Parameter", "OriginY");
            mDockSetParameter.pwmCycleTDefault = (uint)ini.ReadIntValue("Parameter", "PwmCycleTDefault");
            mDockSetParameter.pwmCycleTReset = (uint)ini.ReadIntValue("Parameter", "PwmCycleTReset");
            mDockSetParameter.pwmCycleTGum = (uint)ini.ReadIntValue("Parameter", "PwmCycleTGum");
            mDockSetParameter.pwmCycleTChabu = (uint)ini.ReadIntValue("Parameter", "PwmCycleTChabu");
            mDockSetParameter.pwmChabuDelay = (uint)ini.ReadIntValue("Parameter", "PwmChabuDelay");
            mDockSetParameter.ShowParameter();

            mDockSetParameter.mAutoActionList.Clear();
            int actionNums = ini.ReadIntValue("ActionInfo", "Nums");
            ActionParas ap;
            for (int i = 0; i < actionNums; i++)
            {
                ap = new ActionParas();
                string strSection = string.Format("Action{0}", i);
                ap.Cmd = (GUM_ACTION)ini.ReadIntValue(strSection, "Cmd");
                ap.Point1X = ini.ReadIntValue(strSection, "StartX");
                ap.Point1Y = ini.ReadIntValue(strSection, "StartY");
                ap.Point2X = ini.ReadIntValue(strSection, "EndX");
                ap.Point2Y = ini.ReadIntValue(strSection, "EndY");
                ap.Radius = ini.ReadIntValue(strSection, "Radius");
                ap.Mode = ini.ReadIntValue(strSection, "Mode");

                mDockSetParameter.mAutoActionList.Add(ap);
            }
        }

        private void 导入ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            OpenFileDialog openFileDialogActionsIni = new OpenFileDialog();
            openFileDialogActionsIni.Filter = "INI文件 (*.ini)|*.ini|所有文件 (*.*)|*.*";
            openFileDialogActionsIni.FilterIndex = 1;
            openFileDialogActionsIni.RestoreDirectory = true;
            if (openFileDialogActionsIni.ShowDialog() == DialogResult.OK)
            {
                try
                {
                    string iniPath = openFileDialogActionsIni.FileName;
                    ImportIniFile(iniPath);
                }
                catch (Exception ex)
                {
                    mLog.LogError("Error: Could not read file from disk. Original error: " + ex.Message + "\n");
                }
                CGumController.mDockMain.DrawAction();
            }
        }

        private void 导出ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            SaveFileDialog saveFileDialog = new SaveFileDialog();
            saveFileDialog.Filter = "INI文件 (*.ini)|*.ini|所有文件 (*.*)|*.*";
            saveFileDialog.FilterIndex = 1;
            saveFileDialog.RestoreDirectory = true;
            if (saveFileDialog.ShowDialog() == DialogResult.OK)
            {
                try
                {
                    string iniPath = saveFileDialog.FileName;
                    ExportIniFile(iniPath);
                }
                catch (Exception ex)
                {
                    mLog.LogError("Error: Could not write file to disk. Original error: " + ex.Message + "\n");
                }
            }
        }

        private void 退出ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        private void 记录Log文件ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            记录Log文件ToolStripMenuItem.Checked = !记录Log文件ToolStripMenuItem.Checked;
            SaveConfigFile();
        }

        private void 退出后提示保存ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            退出后提示保存ToolStripMenuItem.Checked = !退出后提示保存ToolStripMenuItem.Checked;
            isSaveTips = 退出后提示保存ToolStripMenuItem.Checked;
            SaveConfigFile();
        }

        private void 启动时检查更新ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            启动时检查更新ToolStripMenuItem.Checked = !启动时检查更新ToolStripMenuItem.Checked;
            isAutoUpdate = 启动时检查更新ToolStripMenuItem.Checked;
            SaveConfigFile();
        }

        private void 关于ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            AboutBox aboutBox = new AboutBox();
            aboutBox.Show();
        }

        private void 串口设置ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            mDockSerialProtocol.Show();
        }

        private void 参数设置ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            mDockSetParameter.Show(dockPanel1);
        }

    }
}
